package com.glorystone.ins.service.impl;

import com.glorystone.ins.common.common.PageVo;
import com.glorystone.ins.dao.AuditTaskMapper;
import com.glorystone.ins.dao.FlowNodeMapper;
import com.glorystone.ins.dao.NoticeRoleMapper;
import com.glorystone.ins.domain.AuditTask;
import com.glorystone.ins.domain.FlowNode;
import com.glorystone.ins.domain.NoticeRole;
import com.glorystone.ins.domain.SysUser;
import com.glorystone.ins.enums.FlowBusinessTypeEnum;
import com.glorystone.ins.enums.FlowOperateTypeEnum;
import com.glorystone.ins.enums.RejectNodeEnum;
import com.glorystone.ins.enums.WorkFlowEnum;
import com.glorystone.ins.interceptor.PageList;
import com.glorystone.ins.service.AuditTaskService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
 * 审批任务服务
 *
 * @author wangwei
 */
@Slf4j
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class AuditTaskServiceImpl implements AuditTaskService {

    @Autowired
    private AuditTaskMapper auditTaskMapper;
    @Autowired
    private FlowNodeMapper flowNodeMapper;
    @Autowired
    private NoticeRoleMapper noticeRoleMapper;


    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void submit(WorkFlowEnum flow, FlowBusinessTypeEnum businessType, Long businessId, FlowOperateTypeEnum operate) {

        log.debug("<--流程信息--> flow-->{}, businessType-->{}, businessId-->{}, operate-->{}", flow.name(), businessType.name(), businessId, operate.name());

        //流程id， 业务类型Id, 业务id, 流程状态   能确认一条正在审批中的流程
        // 1. 首先从审批任务表里看是否存在已经在待办的数据
        AuditTask task = AuditTask.builder()
                .flowId(flow.getValue())
                .businessType(businessType.getValue())
                .businessId(businessId)
                .status(AuditTask.AuditTaskStatusEnum.TO_DO.getValue()).build();

        switch (operate) {
            case START:
                startWorkFlow(task);
                break;
            case PASS:
                passWorkFlow(task);
                break;
            case REJECT:
                rejectWorkFlow(task, null);
                break;
            default:
                break;
        }


        log.debug("<--流程审批结束！-->");
    }

    @Override
    public void submit(WorkFlowEnum flow, FlowBusinessTypeEnum businessType, Long businessId, FlowOperateTypeEnum operate, RejectNodeEnum node) {
        log.debug("<--流程信息--> flow-->{}, businessType-->{}, businessId-->{}, operate-->{}", flow.name(), businessType.name(), businessId, operate.name());

        //流程id， 业务类型Id, 业务id, 流程状态   能确认一条正在审批中的流程
        // 1. 首先从审批任务表里看是否存在已经在待办的数据
        AuditTask task = AuditTask.builder()
                .flowId(flow.getValue())
                .businessType(businessType.getValue())
                .businessId(businessId)
                .status(AuditTask.AuditTaskStatusEnum.TO_DO.getValue()).build();

        switch (operate) {
            case START:
                startWorkFlow(task);
                break;
            case PASS:
                passWorkFlow(task);
                break;
            case REJECT:
                rejectWorkFlow(task, node.getValue());
                break;
            default:
                break;
        }


        log.debug("<--流程审批结束！-->");
    }

    private void rejectWorkFlow(AuditTask task, Integer rejectNodeId) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();

        AuditTask auditTask = auditTaskMapper.findOne(task);
        if (auditTask == null) {
            log.warn("<--不存在待审批流程！-->");
            return;
        }
        FlowNode nowNode = flowNodeMapper.findByTid(auditTask.getNodeId());
        auditTask.setStatus(AuditTask.AuditTaskStatusEnum.DONE.getValue());
        // 当前登录人
        if (user == null) {
            auditTask.setAuditBy(1L);
        } else {
            auditTask.setAuditBy(user.getTid());
        }
        auditTask.setAuditResult(AuditTask.AuditResultEnum.REJECT.getValue());
        auditTask.setAuditAt(LocalDateTime.now());
        auditTaskMapper.update(auditTask);

        // 处理通知
        handleNotice(auditTask, AuditTask.AuditResultEnum.REJECT);

        // 驳回到新节点
        FlowNode rejectTo;
        if (rejectNodeId != null) {
            rejectTo = flowNodeMapper.findByTid(rejectNodeId);
        } else {
            rejectTo = flowNodeMapper.findByTid(nowNode.getRejectTo());
        }

        if (rejectTo.getType() == FlowNode.NodeTypeEnum.FIRST.getValue()) {
            // 如果是驳回到第一个节点，那么就流程结束
            List<FlowNode> nodeList = flowNodeMapper.findByFLowId(task.getFlowId());
            FlowNode last = nodeList.stream().filter(i -> i.getType() == FlowNode.NodeTypeEnum.OVER.getValue()).collect(Collectors.toList()).get(0);
            auditTask.setNodeId(last.getTid());
            auditTaskMapper.update(auditTask);

            return;
        }


        auditTask.setName(nowNode.getRejectName());
        auditTask.setStatus(AuditTask.AuditTaskStatusEnum.TO_DO.getValue());

        auditTask.setNodeId(rejectTo.getTid());
        auditTask.setPermissionCode(rejectTo.getPermissionCode());
        auditTask.setUrl(rejectTo.getUrl() + task.getBusinessId());

        // 当前登录人
        if (user == null) {

            auditTask.setSubmitBy(1L);
        } else {
            auditTask.setSubmitBy(user.getTid());
        }
        auditTask.setSubmitAt(LocalDateTime.now());
        auditTask.cleanAudit();
        auditTaskMapper.save(auditTask);


    }


    private void passWorkFlow(AuditTask task) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();

        AuditTask auditTask = auditTaskMapper.findOne(task);
        if (auditTask == null) {
            log.warn("<--不存在待审批流程！-->");
            return;
        }
        FlowNode nowNode = flowNodeMapper.findByTid(auditTask.getNodeId());
        auditTask.setStatus(AuditTask.AuditTaskStatusEnum.DONE.getValue());
        // 当前登录人
        auditTask.setAuditBy(user.getTid());
        auditTask.setAuditResult(AuditTask.AuditResultEnum.PASS.getValue());
        auditTask.setAuditAt(LocalDateTime.now());
        auditTaskMapper.update(auditTask);

        // 操作渠道
        handleNotice(auditTask, AuditTask.AuditResultEnum.PASS);

        FlowNode nextNode = flowNodeMapper.findByTid(nowNode.getNextId());
        // 下一个流程是否是结束, 不是就新建
        if (nextNode.getType() != FlowNode.NodeTypeEnum.OVER.getValue()) {
            auditTask.setName(nowNode.getPassName());
            auditTask.setNodeId(nextNode.getTid());
            auditTask.setPermissionCode(nextNode.getPermissionCode());
            auditTask.setUrl(nextNode.getUrl() + task.getBusinessId());
            auditTask.setStatus(AuditTask.AuditTaskStatusEnum.TO_DO.getValue());
            // 当前登录人
            auditTask.setSubmitBy(user.getTid());
            auditTask.setSubmitAt(LocalDateTime.now());
            auditTask.cleanAudit();
            auditTaskMapper.save(auditTask);
        }


    }

    /**
     * 处理通知
     * @param auditTask
     * @param auditResult
     */
    private void handleNotice(AuditTask auditTask, AuditTask.AuditResultEnum auditResult) {
        final SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        List<NoticeRole> noticeRoleList = noticeRoleMapper.findByNodeIdAndReason(auditTask.getNodeId(), auditResult.getValue());
        noticeRoleList.forEach(i -> {
            AuditTask task = AuditTask.builder()
                    .name(i.getName())
                    .status(AuditTask.AuditTaskStatusEnum.WAIT_VIEW.getValue())
                    .flowId(auditTask.getFlowId())
                    .nodeId(i.getNodeId())
                    .businessType(auditTask.getBusinessType())
                    .businessId(auditTask.getBusinessId())
                    .url(i.getUrl() + auditTask.getBusinessId())
                    .submitAt(LocalDateTime.now()).build();
                    if(user==null){
                        task.setSubmitBy(1L);
                    }else{
                        task.setSubmitBy(user.getTid());
                    }
            auditTaskMapper.save(task);
        });



    }

    private void startWorkFlow(AuditTask task) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();

        boolean isExists = isExists(task);
        if (isExists) {
            log.warn("<--已经启动过流程！-->");
            return;
        }

        // 生成第一个节点已审批通过的数据， 生成第二个节点待办的数据
        /*List<FlowNode> nodeList = flowNodeMapper.findByFLowId(task.getFlowId());
        FlowNode first = nodeList.stream().filter(i -> i.getType() == FlowNode.NodeTypeEnum.FIRST.getValue()).collect(Collectors.toList()).get(0);
        task.setName(first.getPassName());
        task.setStatus(AuditTask.AuditTaskStatusEnum.DONE.getValue());
        task.setNodeId(first.getTid());
        // 当前登录人
        task.setSubmitBy(user.getTid());
        task.setSubmitAt(LocalDateTime.now());
        task.setAuditBy(user.getTid());
        task.setAuditResult(AuditTask.AuditResultEnum.PASS.getValue());
        task.setAuditAt(LocalDateTime.now());
        auditTaskMapper.save(task);*/

        List<FlowNode> nodeList = flowNodeMapper.findByFLowId(task.getFlowId());
        FlowNode first = nodeList.stream().filter(i -> i.getType() == FlowNode.NodeTypeEnum.FIRST.getValue()).collect(Collectors.toList()).get(0);

        FlowNode node = flowNodeMapper.findByTid(first.getNextId());
        task.setName(first.getPassName());
        task.setStatus(AuditTask.AuditTaskStatusEnum.TO_DO.getValue());
        task.setNodeId(first.getNextId());
        task.setPermissionCode(node.getPermissionCode());
        task.setUrl(node.getUrl() + task.getBusinessId());
        task.setSubmitBy(user.getTid());
        task.setSubmitAt(LocalDateTime.now());
        task.cleanAudit();
        auditTaskMapper.save(task);

    }


    @Override
    public boolean isExists(AuditTask task) {
        return auditTaskMapper.findOne(task) != null;
    }

    @Override
    public PageList<AuditTask> findList(PageVo vo) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();

        // 管理员看到全部数据，方便测试
//        if (1 == user.getUserLevel()) {
//            return auditTaskMapper.findList(vo, vo.getPageable(), null);
//        }
        Set<String> permissions = user.getStringPermissions();

        return auditTaskMapper.findList(vo, vo.getPageable(), permissions);
    }

    @Override
    public AuditTask findOne(AuditTask task) {
        return auditTaskMapper.findOne(task);
    }

    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateViewToDone(Long id) {
        SysUser user = (SysUser) SecurityUtils.getSubject().getPrincipal();
        AuditTask param = new AuditTask();
        param.setTid(id);
        param.setStatus(AuditTask.AuditTaskStatusEnum.DONE.getValue());
        param.setAuditBy(user.getTid());
        param.setAuditAt(LocalDateTime.now());
        auditTaskMapper.update(param);
    }


}
